今天要建立第一個真正的 UI 元件:src/components/ArrivalList.js,把昨天處理好的資料畫出來。
因為我們用的是原生 JavaScript(沒有用 React / Vue),元件的概念會用「一個函式,負責產生並回傳一段 DOM」來實現:
// src/components/ArrivalList.js
export function renderArrivalList(container, arrivals) {
container.innerHTML = ''; // 先清空
if (arrivals.length === 0) {
container.innerHTML = '<p>目前沒有即時資料</p>';
return;
}
const list = document.createElement('ul');
list.className = 'arrival-list';
arrivals.forEach((item) => {
const li = document.createElement('li');
li.className = 'arrival-item';
li.innerHTML = `
<span class="stop-name">${item.stopName}</span>
<span class="eta">${item.etaMinutes ?? '--'} 分鐘</span>
`;
list.appendChild(li);
});
container.appendChild(list);
}
// src/main.js
import { fetchBusArrivals, normalizeArrivals } from './api/tdx.js';
import { renderArrivalList } from './components/ArrivalList.js';
const arrivalContainer = document.getElementById('arrival-list');
async function loadArrivals() {
const raw = await fetchBusArrivals('Taipei', '0100000A00');
const arrivals = normalizeArrivals(raw);
renderArrivalList(arrivalContainer, arrivals);
}
loadArrivals();
在 src/style.css 補上:
.arrival-list { list-style: none; padding: 0; }
.arrival-item {
display: flex;
justify-content: space-between;
padding: 12px;
border-bottom: 1px solid #eee;
}
.eta { font-weight: bold; color: #2563eb; }
存檔後回到瀏覽器,應該就能看到一份即時更新的站牌清單,每一列顯示站名與預估到站分鐘數。
這是整個專案第一次「資料到畫面」的完整閉環,很值得停下來截圖紀念一下!明天我們要加上自動更新機制,讓資料每隔一段時間就自己刷新,不用手動重新整理頁面。